<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #canvas {
            background: rebeccapurple;
        }
    </style>
</head>
<body>

<div style="border: solid 1px darkgreen">
    <canvas id="canvas"></canvas>
</div>

<script>
    const canvas = document.getElementById('canvas')
    canvas.width = 800
    canvas.height = 800
    const ctx = canvas.getContext('2d')

    drawDashed()
    drawDashed2(ctx)
    drawDashed3(ctx)

    function drawDashed() {
        ctx.lineWidth = 4;
        ctx.strokeStyle = 'green';
        ctx.beginPath();
        ctx.setLineDash([5, 15]);
        ctx.moveTo(20, 20);
        ctx.lineTo(400, 20);
        ctx.stroke();
    }

    function drawDashed2(ctx) {
        ctx.lineWidth = 4;
        ctx.strokeStyle = 'red';
        ctx.beginPath();
        ctx.setLineDash([5]);
        ctx.moveTo(0, 60);
        ctx.lineTo(400, 60);
        ctx.stroke();

        ctx.lineWidth = 4;
        ctx.strokeStyle = 'red';
        ctx.beginPath();
        ctx.setLineDash([]);
        ctx.moveTo(0, 100);
        ctx.lineTo(400, 100);
        ctx.stroke();
    }

    function drawDashed3(ctx) {
        ctx.lineWidth = 4;

        ctx.strokeStyle = 'blue';
        ctx.beginPath();
        ctx.setLineDash([20, 5]);
        ctx.moveTo(20, 140);
        ctx.lineTo(380, 140);
        ctx.stroke();

        ctx.strokeStyle = 'green';
        ctx.beginPath();
        // 如果参数 segments元素的数量是奇数， 数组的元素会被复制并重复。[10, 20, 30] 会变成 [10, 20, 30, 10, 20, 30]。
        ctx.setLineDash([10, 20, 30]);
        ctx.moveTo(20, 180);
        ctx.lineTo(380, 180);
        ctx.stroke();
        console.log(ctx.getLineDash()); // [10, 20, 30, 10, 20, 30]

        ctx.strokeStyle = 'red';
        ctx.beginPath();
        ctx.setLineDash([10, 20, 30, 40]);
        ctx.moveTo(20, 220);
        ctx.lineTo(380, 220);
        ctx.stroke();
    }

    var moveToFunction = CanvasRenderingContext2D.prototype.moveTo;
    CanvasRenderingContext2D.prototype.moveToLocation = {};

    // 重新定义moveTo方法
    CanvasRenderingContext2D.prototype.moveTo = function (x, y) {
        this.moveToLocation.x = x;
        this.moveToLocation.y = y;
        moveToFunction.apply(this, [x, y]);
    };

    CanvasRenderingContext2D.prototype.dashedLineTo = function (x, y, dashedLength) {
        dashedLength = dashedLength === undefined ? 5 : dashedLength;
        var startX = this.moveToLocation.x;
        var startY = this.moveToLocation.y;
        var deltaX = x - startX;
        var deltaY = y - startY;
        var numberDash = Math.floor(Math.sqrt(deltaX * deltaX + deltaY * deltaY) / dashedLength);
        for (var i = 0; i < numberDash; i++) {
            this[i % 2 === 0 ? 'moveTo' : 'lineTo'](startX + (deltaX / numberDash) * i, startY + (deltaY / numberDash) * i); //等同于this.moveTo(x, y)或者 this.LineTo(x, y)
        }
        this.moveTo(x, y); //连续绘制虚线时，起点从当前点开始
    };

    //绘制虚线
    ctx.lineWidth = 3;
    ctx.strokeStyle = 'green';
    ctx.moveTo(20, 220);
    ctx.dashedLineTo(200, 400);
    ctx.dashedLineTo(300, 300, 10);
    ctx.dashedLineTo(400, 600);
    ctx.stroke();
</script>
</body>
</html>
